/*
 * msl.c
 * スプライト表示サブルーチン
 * １０進数字表示・ゲームオーバー表示
 */
/* これを定義するとスプライトライブラリが
   マクロを使うようになるので少し早くなる */
#define ASL_USE_MACRO

/* 諸々設定 */
#define CHAR_GAP      33            /* タイムの上桁と下桁の位置の差 */
#define SPRITE_OFFSET 16            /* タイム表示時の位置オフセット */
#define RADAR_X       20            /* レーダー・レーダー枠の中心位置 */
#define RADAR_Y       22            /* レーダー・レーダー枠の中心位置 */

/* スプライトテーブル開始位置                 */
/* （スプライトフォントと同バンクにいるので、 */
/*   フォントがある分先頭番号をずらしている） */
#define SCT_TOP       1344          /* ＳＣＴ先頭番号 */
#define USER_SCT      SCT_TOP + 2   /* 文字列表示用 */
#define TIMER_SCT     SCT_TOP + 0   /* 時計表示用 */
#define TIMER_SCT2    SCT_TOP + 1   /* 時計表示用 */
#define RADAR_SCT     SCT_TOP + 2   /* レーダー枠用 */
#define RADAR_SCT2    SCT_TOP + 3   /* ２プレイヤー時レーダー枠用 */
#define POINT_SCT     SCT_TOP + 4   /* レーダー内ポイント用 */
#define POINT_SCT2    SCT_TOP + 6   /* レーダー内ポイント用 */

/* アナウンス文字の表示中心位置 */
#define ANNOUNCE_X    128
#define ANNOUNCE_Y    80

/* テクスチャーバッファ内での各特定パターンの位置 */
/* 空白パターン */
#define SPACE_POS_X   224
#define SPACE_POS_Y   48

/* Now loading.. */
#define LOAD_POS_X    128
#define LOAD_POS_Y    112
#define LOAD_SIZE_X   80
#define LOAD_SIZE_Y   16

/* モード選択用カーソル */
#define CUR_POS_X     192
#define CUR_POS_Y     48
#define CUR_SIZE_X    16
#define CUR_SIZE_Y    16

/* レーダーに使うポイントパターンの位置 */
/* レーダールーチン内を書き換えるとポイントの色が変わる */
#define RED_POS_X     144           /* 赤 */
#define RED_POS_Y     48
#define BLUE_POS_X    152           /* 青 */
#define BLUE_POS_Y    48
#define YELLOW_POS_X  144           /* 黄 */
#define YELLOW_POS_Y  56
#define GREEN_POS_X   152           /* 緑 */
#define GREEN_POS_Y   56

/* レーダーに使うポイントの大きさの設定 */
/* フォントの都合上１〜８まで */
#define RADER_SIZE_X  2
#define RADER_SIZE_Y  2

/* １秒の基準 */
#define ___1Sec       60            /* 60分の1秒単位 */

/* レーダー番号の定義 */
enum {
  RADAR_1,
  RADAR_2,
};

#include <system.h>
#include <v93.h>
#include <farl.h>
#include <asl.h>
#include <vpsg.h>
#include <libm.h>
#include <common.h>
#include "spec.h"
#include "vardecl.h"
#include "psgdef.h"
#include "math.h"
#include "service.h"
#include "funcdecl.h"

#pragma optimize(on -r)

#define FIELD_MAX (GroundEdgeLoc)
#define another(x) ((x == PLAYER1) ? PLAYER2 : PLAYER1)

/*
========================================
  ASLを用いてスプライトを表示した場合に
  表示処理が終わるまでまつ。
  この処理を行わずにスプライトを使うと
  スプライトがかける事があるのでスプライ
  トを使う場合は必ず呼ぶこと。
  引き数：なし
  戻り値：なし
========================================
 */
void
MSLSync(void)
{
  /* この関数は変更しないでください。 */
  FarlDummySwap();
  FarlSetMemReg(FARL_INTERRUPT_CLEAR_REG,FARL_INTERRUPT_PESYNC);
  FarlSetPEControlReg(FARL_PE_PES | FARL_PE_TLEN);
  while((FarlGetMemReg(FARL_INTERRUPT_STATUS_REG) & FARL_INTERRUPT_PESYNC)==0);
}

/*
========================================
  指定キャラクタをスプライトとして表示する場合に
  必要なパラメータを指定された構造体にセットする。
  ちなみに、テクスチャーバンクは常にTBANK_FONTとなる。
  バンク０以外の場合は、ユーザー側であわせること。
  回転中心軸も、A-Zでは、12,12 0-9では、16,16に
  セットされる。これ以外を中心にしたい場合は
  ユーザー側であわせること。
  A - Z , 0 - 9 以外の文字では正常に動作しない
  引き数：char cChar, ASLSource *src
        cChar 指定したいキャラクタ
        *src  指定結果を保存するASLSource構造体
  戻り値：なし
========================================
*/
void
MSLGetPos(char cChar,ASLSource *src)
{
  char  temp;
  
  /* 指定フォントでは、英文字と数字の幅が違うので場合分けをする */
  /* Ａ〜Ｚまでと少し */
  if (cChar >='A' && cChar <= '_') {
    temp = cChar - 'A';
    src->x_pos = (temp % 10) * 24;
    src->y_pos = (temp / 10) * 24;
    src->x_size = 24;
    src->y_size = 24;
    src->x_hot = 12;
    src->y_hot = 12;
  } else if (cChar >='0') {  /* ０〜 */
    temp = cChar - '0';
    src->x_pos = (temp % 8) * 32;
    src->y_pos = (temp / 8) * 32 + 80;
    src->x_size = 32;
    src->y_size = 32;
    src->x_hot = 16;
    src->y_hot = 16;
  } else if (cChar == ' ') {  /* 空白だった場合 */
    src->x_pos = SPACE_POS_X;
    src->y_pos = SPACE_POS_Y;
    src->x_size = 24;
    src->y_size = 24;
    src->x_hot = 12;
    src->y_hot = 12;
  }
  src->bank = TBANK_FONT;
}

/*
========================================
  フォントのユーザー領域に指定文字列のテクスチャーイメージ
  を作成する。半角大文字のみ。１０文字まで可
  １０文字以上は、正常に動作しない。
  また、USE_MEMCOPYを defineすることにより高速化可能(A2.0)
  以前に定義された文字列は消去しないので、以前に定義した
  文字列より短い場合は、以前の文字列が残る。
  引き数：char *cString
        cString 作成したい文字列
========================================
*/
void
MSLMakeString(char *cString)
{
  char            cLength;
  int             i;
  int             y;
  unsigned long   ulWriteAddress;
  ASLSource       src;

  /* 文字列の長さを取得 */
  cLength = strlen(cString);
  /* 書き込むイメージバンクを設定 */
  FarlSetMemReg(FARL_CMT_BANK_SELECT_REG, TBANK_FONT);
  /* 文字数分のループ */
  for (i = 0; i < cLength; i++) {
    /* 文字開始位置の取得 */
    MSLGetPos(*(cString + i), &src);
    /* 書き込みアドレスの生成 */
    ulWriteAddress = FARL_TEXTURE_BUFFER + i * 24;
    /* 縦２４ドット分のループ */
    for (y = 0; y < 24; y++) {
      /* ２４ドット分の転送 （fontbuf[] にフォントが格納されている事が条件）*/
      int t;
      for (t = 0; t < 24; t++) {
        FarlWriteTxtXYUnpk(i * 24 + t, y + 144,
          fontbuf[src.x_pos+t+src.y_pos*256+y*256]);
      }
    }
  }
}

/*
========================================
  ユーザー領域を表示するのに必要なパラメータを設定する。
  また、MSLMakeStringを使い指定文字列の生成も行う．
  引き数：char *cString, ASLSource *src
        *cString  作成したい文字列
        *src      作成した文字列のパラメータをセットしたいASLSource 構造体
  戻り値：なし
========================================
*/
void
MSLGetString( char *cString, ASLSource *src)
{
  /* 文字列を生成する */
  MSLMakeString(cString);
  /* 構造体のパラメータを設定 */
  /* バンクのセット */
  src->bank = TBANK_FONT;
  /* Ｘ座標初期位置（固定）*/
  src->x_pos = 0;
  /* Ｙ座標初期位置（固定）*/
  src->y_pos = 144;
  /* 文字列の長さに応じて終端位置を設定 */
  /* 24 x 24 ドットフォントとして計算 */
  src->x_size = 24 * strlen(cString);
  src->y_size = 24;
  /* 指定座標を中心にくるようにする */
  /* こうしないと、回転する場合に回転軸が中心ではなくなる */
  src->x_hot = 12 * strlen(cString);
  src->y_hot = 12;
}
/*
----------------------------------------
  レーダーの表示（レーダー枠）
  単独で使っても、AGLShot他をやらないと
  表示されません。（他の関数も同様）
  引き数：int number
      number : RADAR_1  四角い枠
               RADAR_2  半円の枠
  戻り値：なし
----------------------------------------
 */
void MSLPutRadarBase(int number, int which, short RadarX, short RadarY)
{
  ASLSource Src;
  ASLSct    Sct;

  /* レーダー枠は、９の後ろにある */
  /* ９ + 1 : 自分中心用  ９ + 2 : 全体用 */
  if (number == RADAR_1){
    MSLGetPos('9' + 2,&Src);
  } else {
    MSLGetPos('9' + 1,&Src);
  }
  /* スプライトを作る */
  ASLMakeSimpleSprite(&Src, RadarX, RadarY, &Sct);
  /* 作ったテーブルをセットして実行する */
  ASLSetSpriteTable(TBANK_FONT, 
                    RADAR_SCT + ((which==PLAYER1) ? 0 : 1), 1, &Sct);
  ASLExecuteSprite(TBANK_FONT, 
                    RADAR_SCT + ((which==PLAYER1) ? 0 : 1), 1);
}

/*
========================================
  レーダー内ポイント表示その１
  （MSLPutRaderBaseを呼び出す)
  フィールド内に自分と敵がどこにいるかを
  表示する
  引き数：int which 
      which : 自分はだれか
  戻り値：なし
========================================
 */
void
MSLPutRadar (int which, short RadarX, short RadarY)
{
  ASLSource Src;
  ASLSct    Sct,Sct2;
  short     PointX,PointY;

  /* ASLMakeSprite に渡す構造体メンバーを設定 */
  Src.bank   = TBANK_FONT;
  Src.x_pos  = BLUE_POS_X;
  Src.y_pos  = BLUE_POS_Y;
  Src.x_size = RADER_SIZE_X; /* ここのサイズを変えるとレーダー内のポイントの */
  Src.y_size = RADER_SIZE_Y; /* 大きさが変わる。 1〜8まで。 */
  Src.x_hot  = 0;
  Src.y_hot  = 0;

  /* レーダー枠を表示 */
  MSLPutRadarBase(RADAR_1, which, RadarX, RadarY);
  /* テーブルを作成 */
  PointX = 
    (short)( ((FIELD_MAX + Locate[which][LY]) / (FIELD_MAX * 2.0)) * 32.0);
  PointY = 
    (short)( ((FIELD_MAX + Locate[which][LX]) / (FIELD_MAX * 2.0)) * 32.0);
  ASLMakeSimpleSprite(&Src, RadarX + 16 - PointX, RadarY + 16 - PointY,&Sct);

  /* ASLMakeSprite に渡す構造体メンバーを設定 */
  Src.bank   = TBANK_FONT;
  Src.x_pos  = RED_POS_X;
  Src.y_pos  = RED_POS_Y;
  Src.x_size = RADER_SIZE_X; /* ここのサイズを変えるとレーダー内のポイントの */
  Src.y_size = RADER_SIZE_Y; /* 大きさが変わる。 1〜8まで。 */
  Src.x_hot  = 0;
  Src.y_hot  = 0;
  PointX = (short)(((FIELD_MAX + Locate[another(which)][LY]) 
            / (FIELD_MAX * 2.0)) * 32.0);
  PointY = (short)(((FIELD_MAX + Locate[another(which)][LX]) 
            / (FIELD_MAX * 2.0)) * 32.0);
  ASLMakeSimpleSprite(&Src,RadarX + 16 - PointX, RadarY + 16 - PointY,&Sct2);
  /* 作ったテーブルをセットして実行する */
  ASLSetSpriteTable(TBANK_FONT, 
      (which == PLAYER1) ? POINT_SCT : POINT_SCT2, 2, &Sct);
  ASLExecuteSprite(TBANK_FONT, 
      (which == PLAYER1) ? POINT_SCT : POINT_SCT2, 2);
}
/*
========================================
  レーダー内ポイント表示その２
  （MSLPutRaderBaseを呼び出す)
  自分を中心として相手の位置を表示する
  ２プレイヤーには未対応
  引き数：direct_t angle, distace dist
        angle : 角度
        dist  : 距離
  戻り値：なし
========================================
 */
void MSLPutRadar2(direct_t angle, distance dist)
{
  ASLSource Src;
  ASLSct    Sct;
  short     PointX,PointY;

  /* ASLMakeSprite に渡す構造体メンバーを設定 */
  Src.bank   = TBANK_FONT;
  Src.x_pos  = RED_POS_X;
  Src.y_pos  = RED_POS_Y;
  Src.x_size = RADER_SIZE_X;
  Src.y_size = RADER_SIZE_Y;
  Src.x_hot  = 0;
  Src.y_hot  = 0;

  /* もし範囲外と判定されていたら画面外に出す */
  if (angle < 0 || dist <= 0) {
    PointX = 100;
    PointY = 100;
  } else {
    if (sintbl[angle] == 0.0) {
      PointX = 0;
    } else {
      PointX = (short)(((dist / (FIELD_MAX * 2.0)) * sintbl[angle]) * 32.0);
    }
    if (costbl[angle] == 0.0) {
      PointY = 0;
    } else {
      PointY = (short)(((dist / (FIELD_MAX * 2.0)) * costbl[angle]) * 32.0);
    }
  }
  /* レーダー枠を表示 */
  MSLPutRadarBase(RADAR_2, PLAYER1, RADAR_X, RADAR_Y);
  /* テーブルを作成 */
  ASLMakeSimpleSprite(&Src, RADAR_X - PointX, RADAR_Y + 15 - PointY, &Sct);
  /* 作ったテーブルをセットして実行する */
  ASLSetSpriteTable(TBANK_FONT, POINT_SCT, 1, &Sct);
  ASLExecuteSprite(TBANK_FONT, POINT_SCT, 1);
}
/*
========================================
  渡された数値を指定した位置に表示する。
  指定のスプライトフォントが TBANK_FONT で指定された
  テクスチャーバッファに転送されていなければならない。
  また同テクスチャーバッファのＹ座標 168 からのイメー
  ジを破壊する。
  ００〜９９まで表示可能
  引き数：char cNum, short x, short y
        cNum : 表示したい数値
        x    : 表示したいＸ座標
        y    : 表示したいＹ座標
  戻り値：なし
========================================
*/
void MSLPutDec(char cNum, short x, short y)
{
  char High,Low;
  ASLSource oHighSrc,oLowSrc;
  ASLSct  cHighSct,cLowSct;
  
  /* 数値を１０進文字列に変換する */
  Low = cNum % 10 + '0';
  High = cNum / 10 + '0';

  /*
   * １０の位のスプライトを生成する 
   */
  /* 構造体の中身を設定する */
  MSLGetPos(High, &oHighSrc);
  /* スプライトテーブルを生成する */
  ASLMakeSimpleSprite(&oHighSrc,x + SPRITE_OFFSET,y + SPRITE_OFFSET,&cHighSct);
  /* スプライトテーブルをテクスチャーバッファに転送する */
  ASLSetSpriteTable(TBANK_FONT, TIMER_SCT, 1, &cHighSct);
  /*
   * １の位のスプライトを生成する
   */
  /* 構造体の中身を設定する */
  MSLGetPos(Low, &oLowSrc);
  /* スプライトテーブルを生成する */
  ASLMakeSimpleSprite(&oLowSrc,
      x + CHAR_GAP + SPRITE_OFFSET, y + SPRITE_OFFSET, &cLowSct);
  /* スプライトテーブルをテクスチャーバッファに転送する */
  ASLSetSpriteTable(TBANK_FONT, TIMER_SCT2, 1, &cLowSct);
  /* テクスチャーバッファに書き込まれたスプライトテーブルを２つ実行する */
  ASLExecuteSprite(TBANK_FONT, TIMER_SCT, 2);
}

/*
========================================
  ゲームオーバー時スプライト表示他
  曲をならして、ゲームオーバーと言い、
  GAME OVERを表示する
  引き数：なし
  戻り値：なし
========================================
*/
void 
GameOver( void )
{
  ASLSource  gameover;
  ASLSct    sct;
  int i;
  
  /* ゲームオーバー曲の演奏 */
  PSGGameOver();
  /* ＰＣＭボリュームの設定 */
  AdpcmVolume(CHANNEL_1, MAX_PCM_VOLUME, MAX_PCM_VOLUME);
  /* げーむおーばー */
  AdpcmPlay(CHANNEL_1, &pInfo[P_GAMEOVER]);
  /* ちょっと待つ */
  ASLSync();
  /* GAME OVERの作成 */
  MSLGetString("          ", &gameover);
  MSLGetString("GAME OVER", &gameover);
  /* GAME OVER が寄ってくる処理 */
  for (i = 3; i < 300; i++) {
    get_pad();
    /* せっかちな人がいたら抜ける */
    if ((pad00.KD_TRG & KP_run) || (pad10.KD_TRG & KP_run))
      break;
    /* 拡大率をかえつつスプライト作成 */
    ASLMakeZoomSprite(&gameover, 128, 120, i, &sct);
    ASLSetSpriteTable(TBANK_FONT, SCT_TOP, 1, &sct);
    ASLExecuteSprite(TBANK_FONT, SCT_TOP, 1);
    /* 表示 */
    ASLSync();
    AGLShot();
    MSLSync();
  }
  /* しゃべり終わるまで待つ */
  AdpcmWait(CHANNEL_1);
  /* ボリュームを下げる */
  AdpcmVolume(CHANNEL_1, MIN_PCM_VOLUME, MIN_PCM_VOLUME);
  AdpcmVolume(CHANNEL_2, MIN_PCM_VOLUME, MIN_PCM_VOLUME);
  /* run が押されていたら抜ける */
  /* GAME OVER 拡大途中でせっかちな人がRUNを押していた場合のために
     KD_TRG ではなく KD_DATを使用する */
  get_pad();
  while (!((pad00.KD_DAT & KP_run) || (pad10.KD_DAT & KP_run))){
    get_pad();
    if (!(psg_musicch() & CH4))
      break;
  }
  /* ちょっと待つ */
  VSyncWait();
  KINGDispOff();
  KINGCls(KING_BG0);
  KINGDispOn();
}

/*
========================================
  ゲームスタート時文字表示他
  引き数：なし
  戻り値：なし
========================================
*/
void GameStart(void)
{
  ASLSource stringbuf;
  ASLSct    stringsct;
  int       i;

  /* ボリューム設定 */
  AdpcmVolume(CHANNEL_1,MAX_PCM_VOLUME,MAX_PCM_VOLUME);
  /* げぃむすたぁと */
  PSGPlay(MU_GAMESTART);
  AdpcmPlay(CHANNEL_1, &pInfo[P_GAMESTART]);
  MSLGetString("          ", &stringbuf);
  MSLGetString("START", &stringbuf);
  /* READY 拡大 */
  for (i = 6; i < 11; i++) {
    /* おきまりの手順です。
       地面を表示しつつスプライトを出す時は、ここを参考にしてください。*/
    /* カメラの設定 */
    SetCamera(PLAYER1);
    /* 地面の設定 */
    SetGround();
    /* 車の描画 */
    DrawObjects(0, 0, PLAYER2);
    /* 地面の描画 */
    DrawGround();
    /* 時間も表示しておく */
    if (playmode == VSCOM)
      MSLPutDec(GetRestTime(), TIMER_X, TIMER_Y);
    else
      MSLPutDec(GetRestTime(), TIMER2_X, TIMER2_Y);
    /* スプライト作成 */
    ASLMakeZoomSprite(&stringbuf, 
        ANNOUNCE_X, ANNOUNCE_Y, 3 + i * 50, &stringsct);
    /* テーブルセット・実行 */
    ASLSetSpriteTable(TBANK_FONT, USER_SCT, 1, &stringsct);
    ASLExecuteSprite(TBANK_FONT, USER_SCT, 1);
    /* タイミングをあわせる */
    ASLSync();
    AGLShot();
    MSLSync();
  }
  /* 約 1秒まつ */
  for (i = 0; i < (int)(___1Sec * 2.3) ; i++) {
    VSyncWait();
  }
}
/*
========================================
  勝利時表示
  引き数：なし
  戻り値：なし
========================================
*/
void
YouWon(void)
{
  ASLSource stringbuf;
  ASLSct    stringsct;
  int i;

  /* ちょっと待つ */
  VSyncWait();
  /* 音楽フェードアウト */
  PSGFadeOut();
  /* ＰＣＭボリューム設定 */
  AdpcmVolume(CHANNEL_1,MAX_PCM_VOLUME,MAX_PCM_VOLUME);
  /* ”ゆぅ うぉん！” */
  AdpcmPlay(CHANNEL_1, &pInfo[P_YOUWON]);
  /* YOU WON を作成する */
  MSLGetString("          ", &stringbuf);
  MSLGetString("YOU WON", &stringbuf);
  /* しゃきっと拡大 */
  for (i = 0 ; i < 6; i++) {
    /* ６０分の１秒待つ （拡大のタイミングをあわせるため）*/
    VSyncWait();
    /* スプライト表示に必要なパラメータを作ってもらう */
    ASLMakeZoomSprite(&stringbuf, 
        ANNOUNCE_X, ANNOUNCE_Y, 3 + i * 70, &stringsct);
    /* 作ったパラメータをセットする */
    ASLSetSpriteTable(TBANK_FONT, USER_SCT, 1, &stringsct);
    /* スプライトの実行 */
    ASLExecuteSprite(TBANK_FONT, USER_SCT, 1);
    /* タイミングをとって、スプライト表示を行う */
    ASLSync();
    AGLShot();
    MSLSync();
  }
  /* 約１秒待つ */
  for (i = 0; i< ___1Sec; i++) {
    VSyncWait();
  }
  /* ＰＣＭの”ぷち”対策 */
  AdpcmVolume(CHANNEL_1,MIN_PCM_VOLUME,MIN_PCM_VOLUME);
  AdpcmVolume(CHANNEL_2,MIN_PCM_VOLUME,MIN_PCM_VOLUME);
  /* ちょっと待つ */
  VSyncWait();
}
/*
========================================
  敗退時表示
  引き数：なし
  戻り値：なし
========================================
*/
void
YouLost(void)
{
  ASLSource stringbuf;
  ASLSct    stringsct;
  int i;

  VSyncWait();
  /* 音楽フェードアウト */
  PSGFadeOut();
  /* ＰＣＭボリューム設定 */
  AdpcmVolume(CHANNEL_1,MAX_PCM_VOLUME,MAX_PCM_VOLUME);
  /* ”ゆぅ ろすと..” */
  AdpcmPlay(CHANNEL_1, &pInfo[P_YOULOST]);
  /* YOU LOST の文字列を作成する */
  MSLGetString("          ", &stringbuf);
  MSLGetString("YOU LOST", &stringbuf);

  /* まっすぐ落とす */
  for (i = 100 ; i < 200; i+= 6) {
    /* ６０分の１秒待つ （落ちるタイミングをあわせるため）*/
    VSyncWait();
    /* スプライト表示に必要なパラメータを作ってもらう */
    ASLMakeZoomSprite(&stringbuf, ANNOUNCE_X, i, 320, &stringsct);
    /* 作ったパラメータをセットする */
    ASLSetSpriteTable(TBANK_FONT, USER_SCT, 1, &stringsct);
    /* スプライトの実行 */
    ASLExecuteSprite(TBANK_FONT, USER_SCT, 1);
    /* タイミングをとって、スプライト表示を行う */
    ASLSync();
    AGLShot();
    MSLSync();
  }
  /* １回はねる */
  for (i = 1; i < 180; i += 6 ) {
    /* ６０分の１秒待つ （はねるタイミングをあわせるため）*/
    VSyncWait();
    /* スプライト表示に必要なパラメータを作ってもらう */
    /* Ｙ座標に与えている式を変えるとはねかたが変わる */
    ASLMakeZoomSprite(&stringbuf, 
        ANNOUNCE_X, (200 - (int)(sintbl[i * 10] * 30.0)), 320, &stringsct);
    /* 作ったパラメータをセットする */
    ASLSetSpriteTable(TBANK_FONT, USER_SCT, 1, &stringsct);
    /* スプライトの実行 */
    ASLExecuteSprite(TBANK_FONT, USER_SCT, 1);
    /* タイミングをとって、スプライト表示を行う */
    ASLSync();
    AGLShot();
    MSLSync();
  }
  /* 約１秒待つ */
  for (i = 0; i< ___1Sec; i++) {
    VSyncWait();
  }
  /* ＰＣＭの”ぷち”対策 */
  AdpcmVolume(CHANNEL_1,MIN_PCM_VOLUME,MIN_PCM_VOLUME);
  AdpcmVolume(CHANNEL_2,MIN_PCM_VOLUME,MIN_PCM_VOLUME);
  /* ちょっと待つ */
  VSyncWait();
}
/*
========================================
  １Ｐ、２Ｐ負け
  whichFall 負けた方（グローバル変数）
  引き数：なし
  戻り値：なし
========================================
*/
void
WhoWon( void )
{
  ASLSource stringbuf,playerbuf;
  ASLSct    stringsct,whosct;
  int i;
  int who;
  unsigned char wonbuf[7] ={" P WON"};
  
  VSyncWait();
  /* 音楽フェードアウト */
  PSGFadeOut();
  /* ＰＣＭのボリュームを設定 */
  AdpcmVolume(CHANNEL_1,MAX_PCM_VOLUME,MAX_PCM_VOLUME);
  /* ”ゆぅ うぉん！” */
  AdpcmPlay(CHANNEL_1, &pInfo[P_YOUWON]);

  /* 一度文字列を削除する */
  MSLGetString("          ", &stringbuf);
  
  /* 落ちてない方の番号を作る */
  /* １は I を、２は￥の場所に作ったフォントを使う */
  /* ￥はエスケープ文字に解釈されるので、重ねなければならない。 */
  who = ((another(whichFall) == PLAYER1) ? 'I' : '\\');
  /* ？Ｐ  ＷＯＮの作成 */
  wonbuf[0] = who;
  MSLGetString(wonbuf,&stringbuf);
  /* しゃきっと拡大 */
  for (i = 0 ; i < 6; i++) {
    /* ６０分の１秒待つ （拡大のタイミングをあわせるため）*/
    VSyncWait();
    /* スプライト表示に必要なパラメータを作ってもらう */
    /* この時のＸ座標を計算で増減させることによって１つの文字列が
       拡大してくるように見えるようになる。（今回はしていない） */
    ASLMakeZoomSprite(&stringbuf, 
        ANNOUNCE_X, ANNOUNCE_Y, 3 + i * 70, &stringsct);
    /* 作ったパラメータをセットする */
    ASLSetSpriteTable(TBANK_FONT, USER_SCT, 1, &stringsct);
    /* スプライトの実行 */
    ASLExecuteSprite(TBANK_FONT, USER_SCT, 1);
    /* タイミングをとって、スプライト表示を行う */
    ASLSync();
    AGLShot();
    MSLSync();
  }
  /* 約１秒待つ */
  for (i = 0; i< ___1Sec; i++) {
    VSyncWait();
  }
  /* ＰＣＭの”ぷち”対策 */
  AdpcmVolume(CHANNEL_1,MIN_PCM_VOLUME,MIN_PCM_VOLUME);
  AdpcmVolume(CHANNEL_2,MIN_PCM_VOLUME,MIN_PCM_VOLUME);
  /* ちょっと待つ */
  VSyncWait();
}

/*
========================================
  カーソル表示
  （スプライトを作って実行するだけ）
  （表示はしない）
192,48 から 16 x 16 のフォントを使う
  引き数：int x, int y
        x : 表示したいＸ座標
        y : 表示したいＹ座標
  戻り値：なし
========================================
*/
void
CurPut(int x, int y)
{
  ASLSource cursr;
  ASLSct    cursr_sct;

  cursr.bank   = TBANK_FONT;
  /* カーソルのパターンは、テクスチャーバンクの 192, 46から
     定義されている */
  cursr.x_pos  = CUR_POS_X;
  cursr.y_pos  = CUR_POS_Y;
  /* カーソルの大きさは 16x16 */
  cursr.x_size = CUR_SIZE_X;
  cursr.y_size = CUR_SIZE_Y;
  /* 0, 0を基準にして表示する */
  cursr.x_hot  = 0;
  cursr.y_hot  = 0;
  
  /* 上で設定したパラメータに x y 座標を足して表示用パラメータを作る */
  ASLMakeSimpleSprite(&cursr, x, y, &cursr_sct);
  /* パラメータのセット */
  ASLSetSpriteTable(TBANK_FONT, USER_SCT, 1, &cursr_sct);
  /* パラメータの実行 */
  ASLExecuteSprite(TBANK_FONT, USER_SCT, 1);
}

/*
========================================
  カーソルを消す
  （スプライトを作って実行するだけ）
  （表示はしない）
  引き数：なし
  戻り値：なし
========================================
*/
void
CurErase(void)
{
  ASLSource cursr;
  ASLSct    cursr_sct;

  cursr.bank   = TBANK_FONT;
  /* カーソルのパターンは、テクスチャーバンクの 192, 46から
     定義されている */
  cursr.x_pos  = CUR_POS_X;
  cursr.y_pos  = CUR_POS_Y;
  /* カーソルの大きさは 16x16 */
  cursr.x_size = CUR_SIZE_X;
  cursr.y_size = CUR_SIZE_Y;
  /* 0, 0を基準にして表示する */
  cursr.x_hot  = 0;
  cursr.y_hot  = 0;
  
  /* 上で設定したパラメータに座標を足して表示用パラメータを作る */
  ASLMakeSimpleSprite(&cursr, -100, -100, &cursr_sct);
  /* パラメータのセット */
  ASLSetSpriteTable(TBANK_FONT, USER_SCT, 1, &cursr_sct);
  /* パラメータの実行 */
  ASLExecuteSprite(TBANK_FONT, USER_SCT, 1);
}

/*
========================================
  ポーズ
  引き数：なし
  戻り値：なし
========================================
*/
void
Pause(void)
{
  ASLSource stringbuf;
  ASLSct    pause_sct;

  MSLGetString("          ", &stringbuf);
  MSLGetString("PAUSE", &stringbuf);
  AdpcmVolume(CHANNEL_2, 
    MAX_PCM_VOLUME - MAX_PCM_VOLUME / 10, 
    MAX_PCM_VOLUME - MAX_PCM_VOLUME / 10);
  /* ポリゴンを書く */
  SetCamera(PLAYER1);
  SetGround();
  DrawObjects(0, 0, PLAYER2);
  DrawGround();
  /* でっかいＰＡＵＳＥを作る */
  ASLMakeZoomSprite(&stringbuf, ANNOUNCE_X, ANNOUNCE_Y, 500, &pause_sct);
  /* パラメータのセット */
  ASLSetSpriteTable(TBANK_FONT, USER_SCT, 1, &pause_sct);
  /* パラメータの実行 */
  ASLExecuteSprite(TBANK_FONT, USER_SCT, 1);
  ASLSync();
  AGLShot();
  MSLSync();
  /* 効果音を止める */
  PSGSeOff();
  /* 他のＰＣＭが鳴り終わるまで待つ */
  /* 待たないと他の音が鳴っていた時には音が出なくなる */
  AdpcmWait(CHANNEL_2);
  /* ポーズ音の再生 */
  AdpcmPlay(CHANNEL_2, &pInfo[P_PAUSE]);
  /* キー入力待ち */
  get_pad();
  while (!((pad00.KD_TRG & KP_run) || (pad10.KD_TRG & KP_run)))
    get_pad();
  /* 最初の音が鳴り終わるまで待つ */
  AdpcmWait(CHANNEL_2);
  /* ポーズ音の再生 */
  AdpcmPlay(CHANNEL_2, &pInfo[P_PAUSE]);
  /* 鳴り終わるまで待つ */
  AdpcmWait(CHANNEL_2);
  /* ＰＣＭの”ぷち”対策 */
  AdpcmVolume(CHANNEL_2, MIN_PCM_VOLUME, MIN_PCM_VOLUME);
  VSyncWait();
  /* アイドリング音オン */
  PSGSeOn(SE_IDLE);
}
/*
========================================
  ＧＯＯＤ  ＪＯＢ表示
========================================
 */
void
GoodJob(void)
{
  ASLSource stringbuf;
  ASLSct    jobsct;
  
  MSLGetString("          ", &stringbuf);
  MSLGetString("GOOD JOB", &stringbuf);
  ASLMakeZoomSprite(&stringbuf, ANNOUNCE_X, ANNOUNCE_Y, 300, &jobsct);
  /* パラメータのセット */
  ASLSetSpriteTable(TBANK_FONT, USER_SCT, 1, &jobsct);
  /* パラメータの実行 */
  ASLExecuteSprite(TBANK_FONT, USER_SCT, 1);
  ASLSync();
  AGLShot();
  MSLSync();
}
/*
========================================
  Now Loading 表示
========================================
 */
void
NowLoading(void)
{
  ASLSource stringbuf;
  ASLSct    loadsct;
  
  stringbuf.bank   = TBANK_FONT;
  /* now loadingのパターンは、テクスチャーバンクの 128, 112から
     定義されている */
  stringbuf.x_pos  = LOAD_POS_X;
  stringbuf.y_pos  = LOAD_POS_Y;
  /* パターンの大きさは 80x16 */
  stringbuf.x_size = LOAD_SIZE_X;
  stringbuf.y_size = LOAD_SIZE_Y;
  /* 0, 0を基準にして表示する */
  stringbuf.x_hot  = 0;
  stringbuf.y_hot  = 0;
  /* 等倍フォントとして(5,5)に表示 */
  ASLMakeZoomSprite(&stringbuf, 5, 5, 256, &loadsct);
  /* パラメータのセット */
  ASLSetSpriteTable(TBANK_FONT, USER_SCT, 1, &loadsct);
  /* パラメータの実行 */
  ASLExecuteSprite(TBANK_FONT, USER_SCT, 1);
  ASLSync();
  AGLShot();
  MSLSync();
}
